package com.zhijian.medical.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.zhijian.medical.dao.local.RoutinePathologyTsMapper;
import com.zhijian.medical.entity.po.Device;
import com.zhijian.medical.entity.po.RoutineHistory;
import com.zhijian.medical.entity.po.RoutinePathologyTs;
import com.zhijian.medical.entity.po.RoutineStepRecord;
import com.zhijian.medical.entity.vo.request.*;
import com.zhijian.medical.entity.vo.response.*;
import com.zhijian.medical.enums.RoutineHistoryEnum;
import com.zhijian.medical.enums.RoutinePathologySampleStepEnum;
import com.zhijian.medical.enums.RoutineTsEnum;
import com.zhijian.medical.service.*;
import com.zhijian.util.page.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.hutool.core.collection.CollectionUtil;
import com.zhijian.util.AssertUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 常规病例-脱水业务处理层
 * 
 * @author auto
 * @version: 1.0
 * @date 2024-07-25 17:49:31
 */
@Slf4j
@Service
public class RoutinePathologyTsServiceImpl implements RoutinePathologyTsService {

	@Autowired
    private RoutinePathologyTsMapper mapper;

    @Autowired
    private RoutineSingleSampleService singleSampleService;

    @Autowired
    private RoutineHistoryService historyService;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private RoutinePathologyTsSjService tsSjService;

    @Autowired
    private DeviceAdjustRecordService adjustRecordService;

    @Autowired
    private RoutineStepService stepService;

    @Autowired
    private RoutineStepRecordService stepRecordService;

    @Autowired
    private RoutineQcService qcService;

    @Autowired
    private CacheService cacheService;

    @Override
    public RoutinePathologyTs selectById(Long id) {
        return mapper.selectByPrimaryKey(id);
    }

    @Override
    public RoutinePathologyTsVo selectVoById(Long id) {
        return mapper.selectVoById(id);
    }

    @Override
    public void deleteById(Long id) {
        mapper.deleteByPrimaryKey(id);
    }

    @Override
    public void deleteByIdList(List<Long> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return;
        }
        mapper.deleteByIdList(idList);
    }

    @Override
    public Long insert(RoutinePathologyTs routinePathologyTs) {
        Date now = new Date();
        routinePathologyTs.setCreateTime(now);
        routinePathologyTs.setUpdateTime(now);
        return mapper.insert(routinePathologyTs) > 0 ? routinePathologyTs.getId() : 0L;
    }

    @Override
    public Long insertSelective(RoutinePathologyTs routinePathologyTs) {
        Date now = new Date();
        routinePathologyTs.setCreateTime(now);
        routinePathologyTs.setUpdateTime(now);
        return mapper.insertSelective(routinePathologyTs) > 0 ? routinePathologyTs.getId() : 0L;
    }

    @Override
    public boolean update(RoutinePathologyTs routinePathologyTs) {
        Date now = new Date();
        routinePathologyTs.setUpdateTime(now);
        return mapper.updateByPrimaryKey(routinePathologyTs) != 0;
    }

    @Override
    public boolean updateByPrimaryKeySelective(RoutinePathologyTs record) {
        Date now = new Date();
        record.setUpdateTime(now);
        return mapper.updateByPrimaryKeySelective(record) != 0;
    }

    @Override
    public boolean save(RoutinePathologyTsSaveOrUpdateVo saveOrUpdateVo) {
        RoutinePathologyTs routinePathologyTs = new RoutinePathologyTs();
        BeanUtils.copyProperties(saveOrUpdateVo, routinePathologyTs);
        return this.insert(routinePathologyTs) != 0;
    }

    @Override
    public boolean modify(RoutinePathologyTsSaveOrUpdateVo saveOrUpdateVo) {
        RoutinePathologyTs old = this.selectById(saveOrUpdateVo.getId());
        AssertUtil.notNull(old, "此数据不存在或者已被删除");
        RoutinePathologyTs routinePathologyTs = new RoutinePathologyTs();
        BeanUtils.copyProperties(saveOrUpdateVo, routinePathologyTs);
        return this.update(routinePathologyTs);
    }

    @Override
    public RoutinePathologyTsVo selectOne(RoutinePathologyTsSearchVo routinePathologyTsSearchVo) {
        return mapper.selectOne(routinePathologyTsSearchVo);
     }

    @Override
    public Integer count(RoutinePathologyTsSearchVo routinePathologyTsSearchVo) {
        return mapper.count(routinePathologyTsSearchVo);
    }

    @Override
    public List<RoutinePathologyTsVo> selectList(RoutinePathologyTsSearchVo routinePathologyTsSearchVo) {
        return mapper.selectList(routinePathologyTsSearchVo);
    }

    @Override
    public Page<RoutinePathologyTsVo> selectPage(RoutinePathologyTsSearchVo routinePathologyTsSearchVo) {
        AssertUtil.check(Objects.isNull(routinePathologyTsSearchVo.getPageNum()) || Objects.isNull(routinePathologyTsSearchVo.getPageSize()), "分页参数不能为空");
        //先直接查总数
        int count = count(routinePathologyTsSearchVo);
        //分页
        Page<RoutinePathologyTsVo> page = new Page<>(true, count, routinePathologyTsSearchVo.getPageNum(), routinePathologyTsSearchVo.getPageSize());
        routinePathologyTsSearchVo.setStartIndex(page.getStartIndex());
        page.setPage(true);
        page.setTotalCount(count);
        List<RoutinePathologyTsVo> responseVos = this.selectList(routinePathologyTsSearchVo);
        page.setData(responseVos);
        return page;
    }

    @Override
    public boolean insertBatch(List<RoutinePathologyTs> entities) {
        return CollectionUtil.isNotEmpty(entities) && mapper.insertBatch(entities) > 0;
    }

    @Override
    public void deleteByCondition(RoutinePathologyTsSearchVo routinePathologyTsSearchVo) {
        //慎重用此方法！！
        mapper.deleteByCondition(routinePathologyTsSearchVo);
    }

    @Transactional(rollbackFor = Exception.class, value = "localTransactionManager")
    @Override
    public boolean inputNums(String numbers) {
        // 先检查是否有设备正在脱水
        RoutinePathologyTs ts = this.selectById(1L);
        boolean tsFlag = ts.getStep().equals(RoutineTsEnum.OVER.getCode().byteValue());
        com.zhijian.medical.util.AssertUtil.check(!tsFlag, "编号：" + ts.getSample() + "正在脱水");
        // 记录脱水历史
        List<RoutineSingleSampleVo> routineSingleSampleVos = singleSampleService.selectList(RoutineSingleSampleSearchVo.builder().tsBasketCode(numbers).build());
        com.zhijian.medical.util.AssertUtil.check(CollUtil.isEmpty(routineSingleSampleVos), "未查询到此脱水框编号");
        List<RoutineHistory> entities = new ArrayList<>();
        Date nowDate = new Date();
        for (RoutineSingleSampleVo vo : routineSingleSampleVos) {
            RoutineHistory history = new RoutineHistory();
            history.setUpdateTime(nowDate);
            history.setCreateTime(nowDate);
            history.setNumber(vo.getNumber());
            history.setStep(RoutineHistoryEnum.TS.getCode().byteValue());
            history.setSampleId(vo.getId());
            entities.add(history);

            // 查询状态，如果是已送片，可以继续，如果非已送片，则检查状态是否有脱水-已脱水则提示错误
            // 正式开发需要优化这段逻辑
            Integer tsCount = historyService.count(RoutineHistorySearchVo.builder()
                    .step(RoutineHistoryEnum.TS.getCode().byteValue())
                    .number(vo.getNumber())
                    .build());
            com.zhijian.medical.util.AssertUtil.check(tsCount > 0, "信息已录入");
        }
        historyService.insertBatch(entities);
        // 修改脱水状态
        // 获取预计完成时间
        // 脱水流程共 14小时：10%甲醛（2小时）、80%乙醇（3小时）、95%乙醇①（2小时）、95%乙醇②（1小时）、无水乙醇①（1小时）、
        // 无水乙醇②（1小时）、二甲苯①（0.5小时）、二甲苯②（0.5小时）、石蜡①（1小时）、石蜡②（1小时）、石蜡③（1小时）
//        DateTime endTime = DateUtil.offset(nowDate, DateField.HOUR, 14);
        // 测试这边改为了 1 分钟
        DateTime endTime = DateUtil.offset(nowDate, DateField.MINUTE, 1);
        if (Objects.isNull(ts.getTsybsDev())) {
            ts.setTsybsDev(0);
        }
        this.updateByPrimaryKeySelective(RoutinePathologyTs.builder()
                        .id(1L)
                        .step(RoutineTsEnum.JQ.getCode().byteValue())
                        .endTime(endTime)
                        .sample(numbers)
                        .leftTime(6 + "")
//                        .leftTime(14*60*60 + "")
                        .tsybs(routineSingleSampleVos.size())
                        .tsybsDev(ts.getTsybsDev() + routineSingleSampleVos.size())
                        .build());

        // 用作 redis 倒计时
//        cacheService.setex("gl_step_ts_time/" + numbers, 2*60*60, "1");
        cacheService.setex("gl_step_ts_time/" + numbers, 6, "1");
        // 获取病理号
        String conventionPathologyNumber = qcService.selectById(routineSingleSampleVos.get(0).getQcId()).getConventionPathologyNumber();
        // 修改状态为脱水
        RoutineStepVo routineStepVo = stepService.selectOne(RoutineStepSearchVo.builder().conventionPathologyNumber(conventionPathologyNumber).build());
        if (routineStepVo.getStep() < RoutinePathologySampleStepEnum.TS.getCode().byteValue()) {
            String contetnt = "在实验室脱水";
            stepService.updateStepByNums(conventionPathologyNumber, contetnt, RoutinePathologySampleStepEnum.TS.getCode().byteValue());
            stepRecordService.insert(RoutineStepRecord.builder()
                    .conventionPathologyNumber(conventionPathologyNumber)
                    .step(RoutinePathologySampleStepEnum.TS.getCode().byteValue())
                    .content(contetnt)
                    .build());
        }
        return true;
    }

    @Override
    public RoutinePathologyTsVo pathologyInfo() {
        RoutinePathologyTsVo tsVo = this.selectVoById(1L);
        // 结算剩余时间
        Long ttl = cacheService.ttl("gl_step_ts_time/" + tsVo.getSample());
        tsVo.setLeftTime(ttl > 0 ? String.valueOf(ttl) : "0");
        // 查找设备信息
        List<Device> devices = deviceService.selectListByType("脱水");
        DeviceTsVo deviceTsVo = new DeviceTsVo();
        if (CollUtil.isNotEmpty(devices)) {
            BeanUtils.copyProperties(devices.get(0), deviceTsVo);
            // 默认维修时间是现在时间- 3 个月
            Date adjustDate = DateUtil.offset(new Date(), DateField.MONTH, -3);
            String adjustTime = DateUtil.formatDateTime(adjustDate);
            // 默认下次维修时间是现在时间+8个月
            adjustDate = DateUtil.offset(new Date(), DateField.MONTH, 8);
            String nextAdjustTime = DateUtil.formatDateTime(adjustDate);
            // 查找维修记录
            List<DeviceAdjustRecordVo> deviceAdjustRecordVos = adjustRecordService.selectList(DeviceAdjustRecordSearchVo.builder().deviceId(deviceTsVo.getId()).build());
            // 有记录
            if (CollUtil.isNotEmpty(deviceAdjustRecordVos)) {
                //adjustTime = deviceAdjustRecordVos.get(0).getCreateTime();
                adjustTime = deviceAdjustRecordVos.get(0).getDate() + " 00:00:00";
                adjustDate = DateUtil.parse(adjustTime);
                nextAdjustTime = DateUtil.formatDateTime(DateUtil.offset(adjustDate, DateField.MONTH, 11));
            }
            deviceTsVo.setJzrq(adjustTime);
            deviceTsVo.setXcjzrq(nextAdjustTime);
        }
        tsVo.setDeviceTsVo(deviceTsVo);
        // 查找试剂信息
        List<RoutinePathologyTsSjVo> routinePathologyTsSjVos = tsSjService.selectList(RoutinePathologyTsSjSearchVo.builder().tsId(1L).build());
        tsVo.setSjVoList(routinePathologyTsSjVos);
        return tsVo;
    }
}